/**
*********************************************************************************************************
*               Copyright(c) 2015, Realtek Semiconductor Corporation. All rights reserved.
**********************************************************************************************************
* @file
* @brief
* @details
* @author
* @date
* @version
*********************************************************************************************************
*/

/* Includes ------------------------------------------------------------------*/
#include "rtl876x_gpio_i2c_wristband.h"
#include "rtl876x_i2c.h"
#include "rtl876x_rcc.h"
#include "rtl876x_gpio.h"
#include "trace.h"
#include "platform_utils.h"
#include "rtl876x_pinmux.h"
#include "rtl876x_tim.h"
#include "rtl876x_nvic.h"
#include "boards.h"
#include "hrs_internal.h"
#include "i2c_mutex.h"
#include "log.h"


#define IIC_MAX_TIMEOUT_US      200
#define SCL_HOLD      1
///*******************************************
#if 0
static volatile bool m_i2c_is_locked = false; 
DATA_RAM_FUNCTION
inline void i2c_set_locked(void)
{
    m_i2c_is_locked = true; 
}
DATA_RAM_FUNCTION
inline void i2c_unset_locked(void)
{
    m_i2c_is_locked = false; 
}
DATA_RAM_FUNCTION
inline bool i2c_check_is_locked(void)
{
    return m_i2c_is_locked;
}
#endif
//Init Example usage
static GPIO_I2C_InitTypeDef  GPIO_I2C_InitStructure;

//#define I2C_DELAY platform_delay_us(GPIO_I2C_InitStructure.delay)
#define I2C_DELAY for(int volatile i=0;i<10;i++)
#define I2C_DELAY_FAST for(int volatile i=0;i<6;i++)

static void GPIO_I2C_Init(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct);
static void GPIO_I2C_StructInit(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct);

void gpio_tp_i2c_driver_init(void)
{
    GPIO_I2C_StructInit(&GPIO_I2C_InitStructure);
    GPIO_I2C_InitStructure.I2C_ClockSpeed   = 400000;
    GPIO_I2C_InitStructure.I2C_AddressMode  = I2C_AddressMode_7BIT;
    GPIO_I2C_InitStructure.I2C_SlaveAddress = 0;
    GPIO_I2C_InitStructure.I2C_SDA_Pin = TP_SDA_PIN;
    GPIO_I2C_InitStructure.I2C_SCL_Pin = TP_SCL_PIN;
    GPIO_I2C_Init(&GPIO_I2C_InitStructure);
	
	Pad_PullConfigValue(GPIO_I2C_InitStructure.I2C_SDA_Pin, PAD_STRONG_PULL);
	Pad_PullConfigValue(GPIO_I2C_InitStructure.I2C_SCL_Pin, PAD_STRONG_PULL);
}
#if 0
//*******************************************/
/**
  * @brief  Deinitializes the I2Cx peripheral registers to their default reset values.
  * @param  I2Cx: where x can be 0 or 1 to select the I2C peripheral.
  * @retval None
  */
__STATIC_INLINE void GPIO_I2C_DeInit(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    Pad_Config(GPIO_I2C_InitStruct->I2C_SCL_Pin, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_UP,
               PAD_OUT_DISABLE, PAD_OUT_HIGH);
    Pad_Config(GPIO_I2C_InitStruct->I2C_SDA_Pin, PAD_SW_MODE, PAD_IS_PWRON, PAD_PULL_UP,
               PAD_OUT_DISABLE, PAD_OUT_HIGH);
}
#endif
__STATIC_INLINE void GPIO_I2C_SET_SCL(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_SetBits(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
}

__STATIC_INLINE void GPIO_I2C_RESET_SCL(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_ResetBits(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
}

__STATIC_INLINE void GPIO_I2C_SET_SDA(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_SetBits(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
}

__STATIC_INLINE void GPIO_I2C_RESET_SDA(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_ResetBits(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
}
__STATIC_INLINE void GPIO_I2C_free_SCL(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO->DATADIR = GPIO->DATADIR & (~GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
}
__STATIC_INLINE void GPIO_I2C_OUT_SCL(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO->DATADIR |= GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin);
    GPIO->DATASRC &= (~GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
}
__STATIC_INLINE void GPIO_I2C_free_SDA(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO->DATADIR = GPIO->DATADIR & (~GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
}
__STATIC_INLINE void GPIO_I2C_OUT_SDA(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO->DATADIR |= GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin);
    GPIO->DATASRC &= (~GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
}

__STATIC_INLINE void GPIO_I2C_start(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    #if 1
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY;
    GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY;
    #else
    GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);

    
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
    I2C_DELAY_FAST;
    GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY_FAST;
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    I2C_DELAY_FAST;
    GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY_FAST;
    #endif
}

__STATIC_INLINE void GPIO_I2C_restart(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    #if 0
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    //I2C_DELAY;
    GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY;
    #else
    GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);

    
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
    //I2C_DELAY;
    GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY;
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    I2C_DELAY;
    GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY;
    #endif
}

__STATIC_INLINE void GPIO_I2C_stop(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY;
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    I2C_DELAY;
    GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
}

DATA_RAM_FUNCTION
static bool GPIO_I2C_wait_ack(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
//    uint16_t timeout = IIC_MAX_TIMEOUT_US;
    uint16_t timeout1 = IIC_MAX_TIMEOUT_US;
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
//    while (timeout--)
//    {
//        if ((GPIO->DATAOUT & GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin)) == RESET)
//        {
            GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
//            break;
//        }
//    }
//    if (timeout == 0)
//    {
//        GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
//        GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
//        return false;
//    }

    I2C_DELAY;

    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);

    while (timeout1--)
    {
        if ((GPIO->DATAIN & GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin)) == RESET)
        {
			I2C_DELAY;
            return true;
        }
    }
    return false;
}

__STATIC_INLINE void GPIO_I2C_send_ack(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY;
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    I2C_DELAY;
}

__STATIC_INLINE void GPIO_I2C_send_nack(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
    I2C_DELAY;
    GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
    I2C_DELAY;
}

__STATIC_INLINE void GPIO_I2C_Configuration(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    Pad_Config(GPIO_I2C_InitStruct->I2C_SCL_Pin, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP,
               PAD_OUT_ENABLE, PAD_OUT_HIGH);
    Pad_Config(GPIO_I2C_InitStruct->I2C_SDA_Pin, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_UP,
               PAD_OUT_ENABLE, PAD_OUT_HIGH);

    Pinmux_Config(GPIO_I2C_InitStruct->I2C_SCL_Pin, DWGPIO);
    Pinmux_Config(GPIO_I2C_InitStruct->I2C_SDA_Pin, DWGPIO);
}

__STATIC_INLINE void GPIO_I2C_BusClear(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_stop(GPIO_I2C_InitStruct);
    GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
    GPIO_I2C_InitStruct->busy_flag = false;
}
/**
  * @brief  check GPIO_I2C_InitTypeDef.
  * @param  GPIO_I2C_InitTypeDef : pointer to a GPIO_I2C_InitTypeDef structure which will be initialized.
  * @retval false error.
  */
DATA_RAM_FUNCTION
static bool GPIO_I2C_CheckStructStatus(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    if ((GPIO_I2C_InitStruct->I2C_ClockSpeed > 400000) |
        (GPIO_I2C_InitStruct->I2C_AddressMode > I2C_AddressMode_10BIT) |
        (GPIO_I2C_InitStruct->I2C_SlaveAddress > 0x400) |
        (GPIO_I2C_InitStruct->I2C_SDA_Pin > H_2) |
        (GPIO_I2C_InitStruct->I2C_SCL_Pin > H_2)
       )
    {
        return false;
    }
    return true;
}

/**
  * @brief  Initializes the GPIO_I2C peripheral according to the specified
  *   parameters in the GPIO_I2C_InitStruct.
  * @param  GPIO_I2C_InitStruct: pointer to a I2C_InitTypeDef structure that
  *   contains the configuration information for the specified GPIO_I2C peripheral.
  * @retval None
  */
static void GPIO_I2C_Init(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    if (GPIO_I2C_CheckStructStatus(GPIO_I2C_InitStruct) == false)
    {
        APP_PRINT_INFO0("GPIO_I2C Check Struct Status error");
    }
    GPIO_I2C_Configuration(GPIO_I2C_InitStruct);
    RCC_PeriphClockCmd(APBPeriph_GPIO, APBPeriph_GPIO_CLOCK, ENABLE);
    GPIO_InitTypeDef GPIO_InitStruct;
    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin    = GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin) |
                                  GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin);
    GPIO_InitStruct.GPIO_Mode   = GPIO_Mode_OUT;
    GPIO_InitStruct.GPIO_ITCmd  = DISABLE;
    GPIO_Init(&GPIO_InitStruct);
    GPIO_I2C_InitStruct->delay = 1;//400000 / GPIO_I2C_InitStruct->I2C_ClockSpeed;
}

/**
  * @brief  Fills each GPIO_I2C_InitTypeDef member with its default value.
  * @param  GPIO_I2C_InitTypeDef : pointer to a GPIO_I2C_InitTypeDef structure which will be initialized.
  * @retval None
  */
static void GPIO_I2C_StructInit(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    GPIO_I2C_InitStruct->I2C_ClockSpeed = 400000;      /*!< Specifies the clock frequency.
                                                This parameter must be set to a value lower than 400kHz */
    GPIO_I2C_InitStruct->I2C_AddressMode =
        I2C_AddressMode_7BIT;     /*!< Specifies the I2C address mode.
                                                This parameter can be a value of @ref I2C_address_mode */

    GPIO_I2C_InitStruct->I2C_SlaveAddress = 0;    /*!< Specifies the first device own address.
                                                This parameter can be a 7-bit or 10-bit address. */
    GPIO_I2C_InitStruct->I2C_SDA_Pin = 0;
    GPIO_I2C_InitStruct->I2C_SCL_Pin = 0;
    //GPIO_I2C_InitStruct->delay = 0;
    GPIO_I2C_InitStruct->busy_flag = 0;
}
DATA_RAM_FUNCTION
static bool GPIO_I2C_BUS_CHECK(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    bool ret = SET;
    GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
    ret = ret & GPIO_ReadInputDataBit(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
    ret = ret & GPIO_ReadInputDataBit(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin));
    GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
    GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
    return !ret;
}
DATA_RAM_FUNCTION
static bool GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct)
{
    return GPIO_ReadInputDataBit(GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SCL_Pin));
}
/**
  * @brief  Send data in master mode through the GPIO_I2C peripheral.
  * @param  I2Cx: where x can be 0 or 1 to select the GPIO_I2C peripheral.
  * @param  Data: Byte to be transmitted..
  * @retval None
  */
DATA_RAM_FUNCTION
static GPIO_I2C_Status GPIO_I2C_MasterWrite_int(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,
                                     uint16_t len)
{
    uint8_t shift;
    uint8_t address_len;
    uint16_t address_data;
    uint16_t index;

	GPIO_I2C_InitStruct=&GPIO_I2C_InitStructure;
	GPIO_I2C_InitStruct->I2C_SlaveAddress=slave;
    if (GPIO_I2C_CheckStructStatus(GPIO_I2C_InitStruct) == false)
    {
        APP_PRINT_INFO0("GPIO_I2C Check Struct Status error");
        return I2C_GPIO_INVALUE;
    }
    if (GPIO_I2C_InitStruct->busy_flag)

    {
        APP_PRINT_INFO0("in w,busy_flag error");
        return I2C_GPIO_BUSY;
    }
    GPIO_I2C_InitStruct->busy_flag = true;
    if (GPIO_I2C_BUS_CHECK(GPIO_I2C_InitStruct))
    {
        GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
        APP_PRINT_INFO0("in w,GPIO_I2C_BUS_CHECK error");
        return I2C_GPIO_BUSY;
    }

    if (GPIO_I2C_InitStruct->I2C_AddressMode)
    {
        address_data = (((GPIO_I2C_InitStruct->I2C_SlaveAddress >> 7) & 0xf6) | 0xf0) |
                       (GPIO_I2C_InitStruct->I2C_SlaveAddress << 8);
    }
    else
    {
        address_data = (GPIO_I2C_InitStruct->I2C_SlaveAddress << 1) & 0xfe;
    }

    GPIO_I2C_start(GPIO_I2C_InitStruct);

    for (address_len = 0; address_len < GPIO_I2C_InitStruct->I2C_AddressMode + 1; address_len++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((address_data >> address_len * 8) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            I2C_DELAY;


            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_ADDR_NOACK;
        }
    }
    for (index = 0; index < len; index++)
    {
        for (shift = 0; shift < 8; shift ++)
        {
#if SCL_HOLD
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
            while (timeout--)
            {
                if (GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitStruct))
                {
                    break;
                }
            }
            if (timeout == 0)
            {
                GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
                return I2C_GPIO_ERR_TIMEOUT;
            }
            GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
#endif
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((*(pBuf + index)) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            I2C_DELAY;
            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_TXDATA_NOACK;
        }
    }

    GPIO_I2C_stop(GPIO_I2C_InitStruct);
    GPIO_I2C_InitStruct->busy_flag = false;
    return I2C_GPIO_Success;
}

static GPIO_I2C_Status GPIO_I2C_MasterWrite_int_no_p(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,
                                     uint16_t len)
{
    uint8_t shift;
    uint8_t address_len;
    uint16_t address_data;
    uint16_t index;

	GPIO_I2C_InitStruct=&GPIO_I2C_InitStructure;
	GPIO_I2C_InitStruct->I2C_SlaveAddress=slave;
    if (GPIO_I2C_CheckStructStatus(GPIO_I2C_InitStruct) == false)
    {
        APP_PRINT_INFO0("GPIO_I2C Check Struct Status error");
        return I2C_GPIO_INVALUE;
    }
    if (GPIO_I2C_InitStruct->busy_flag)

    {
        return I2C_GPIO_BUSY;
    }
    GPIO_I2C_InitStruct->busy_flag = true;
    if (GPIO_I2C_BUS_CHECK(GPIO_I2C_InitStruct))
    {
        GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
        return I2C_GPIO_BUSY;
    }

    
    if (GPIO_I2C_InitStruct->I2C_AddressMode)
    {
        address_data = (((GPIO_I2C_InitStruct->I2C_SlaveAddress >> 7) & 0xf6) | 0xf0) |
                       (GPIO_I2C_InitStruct->I2C_SlaveAddress << 8);
    }
    else
    {
        address_data = (GPIO_I2C_InitStruct->I2C_SlaveAddress << 1) & 0xfe;
    }
	GPIO_I2C_start(GPIO_I2C_InitStruct);
    for (address_len = 0; address_len < GPIO_I2C_InitStruct->I2C_AddressMode + 1; address_len++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((address_data >> address_len * 8) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            I2C_DELAY;


            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_ADDR_NOACK;
        }
    }
    for (index = 0; index < len; index++)
    {
        for (shift = 0; shift < 8; shift ++)
        {
#if SCL_HOLD
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
            while (timeout--)
            {
                if (GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitStruct))
                {
                    break;
                }
            }
            if (timeout == 0)
            {
                GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
                return I2C_GPIO_ERR_TIMEOUT;
            }
            GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
#endif
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((*(pBuf + index)) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            I2C_DELAY;
            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_TXDATA_NOACK;
        }
    }

    //GPIO_I2C_stop(GPIO_I2C_InitStruct);
    GPIO_I2C_InitStruct->busy_flag = false;
    return I2C_GPIO_Success;
}
DATA_RAM_FUNCTION
static GPIO_I2C_Status GPIO_I2C_MasterRead_int(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,
                                    uint16_t len)
{
    uint8_t shift;
    uint8_t address_len;
    uint16_t address_data;
    uint16_t index;
		GPIO_I2C_InitStruct=&GPIO_I2C_InitStructure;
		GPIO_I2C_InitStruct->I2C_SlaveAddress=slave;
    if (GPIO_I2C_CheckStructStatus(GPIO_I2C_InitStruct) == false)
    {
        APP_PRINT_INFO0("GPIO_I2C Check Struct Status error");
        return I2C_GPIO_INVALUE;
    }
    if (GPIO_I2C_InitStruct->busy_flag)
    {
        return I2C_GPIO_BUSY;
    }
    GPIO_I2C_InitStruct->busy_flag = true;
    if (GPIO_I2C_BUS_CHECK(GPIO_I2C_InitStruct))
    {
        GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
        return I2C_GPIO_BUSY;
    }

    if (GPIO_I2C_InitStruct->I2C_AddressMode)
    {
        address_data = (((GPIO_I2C_InitStruct->I2C_SlaveAddress >> 7) & 0xf6) | 0xf1) |
                       (GPIO_I2C_InitStruct->I2C_SlaveAddress << 8);
    }
    else
    {
        address_data = (GPIO_I2C_InitStruct->I2C_SlaveAddress << 1) | 0x01;
    }
	
    GPIO_I2C_start(GPIO_I2C_InitStruct);

    for (address_len = 0; address_len < GPIO_I2C_InitStruct->I2C_AddressMode + 1; address_len++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((address_data >> address_len * 8) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            I2C_DELAY;


            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_ADDR_NOACK;
        }
    }

    for (index = 0; index < len; index++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
#if SCL_HOLD
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
            while (timeout--)
            {
                if (GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitStruct))
                {
                    break;
                }
            }
            if (timeout == 0)
            {
                GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
                return I2C_GPIO_ERR_TIMEOUT;
            }
            GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
#endif
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
            I2C_DELAY;
            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
            if ((GPIO->DATAIN & GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin)))
            {
                *(pBuf + index) |= BIT(7 - shift);
            }
            else
            {
                *(pBuf + index) &= ~BIT(7 - shift);
            }
        }
        if (index == len - 1)
        {
            GPIO_I2C_send_nack(GPIO_I2C_InitStruct);
        }
        else
        {
            GPIO_I2C_send_ack(GPIO_I2C_InitStruct);
        }
    }
    GPIO_I2C_stop(GPIO_I2C_InitStruct);
    GPIO_I2C_InitStruct->busy_flag = false;
    return I2C_GPIO_Success;


}

static GPIO_I2C_Status GPIO_I2C_MasterRead_int_no_p(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,
                                    uint16_t len)
{
    uint8_t shift;
    uint8_t address_len;
    uint16_t address_data;
    uint16_t index;
		GPIO_I2C_InitStruct=&GPIO_I2C_InitStructure;
		GPIO_I2C_InitStruct->I2C_SlaveAddress=slave;



    if (GPIO_I2C_InitStruct->I2C_AddressMode)
    {
        address_data = (((GPIO_I2C_InitStruct->I2C_SlaveAddress >> 7) & 0xf6) | 0xf1) |
                       (GPIO_I2C_InitStruct->I2C_SlaveAddress << 8);
    }
    else
    {
        address_data = (GPIO_I2C_InitStruct->I2C_SlaveAddress << 1) | 0x01;
    }
	
    GPIO_I2C_start(GPIO_I2C_InitStruct);	
	
    for (address_len = 0; address_len < GPIO_I2C_InitStruct->I2C_AddressMode + 1; address_len++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((address_data >> address_len * 8) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            I2C_DELAY;


            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_ADDR_NOACK;
        }
    }

    for (index = 0; index < len; index++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
#if SCL_HOLD
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
            while (timeout--)
            {
                if (GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitStruct))
                {
                    break;
                }
            }
            if (timeout == 0)
            {
                GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
                return I2C_GPIO_ERR_TIMEOUT;
            }
            GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
#endif
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
            I2C_DELAY;
            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
            if ((GPIO->DATAIN & GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin)))
            {
                *(pBuf + index) |= BIT(7 - shift);
            }
            else
            {
                *(pBuf + index) &= ~BIT(7 - shift);
            }
        }
        if (index == len - 1)
        {
            GPIO_I2C_send_nack(GPIO_I2C_InitStruct);
        }
        else
        {
            GPIO_I2C_send_ack(GPIO_I2C_InitStruct);
        }
    }
    GPIO_I2C_stop(GPIO_I2C_InitStruct);
    GPIO_I2C_InitStruct->busy_flag = false;
    return I2C_GPIO_Success;


}

DATA_RAM_FUNCTION
static GPIO_I2C_Status GPIO_TP_I2C_MasterRepeatRead_int(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,uint16_t len,uint8_t *prBuf, uint16_t rlen)
{
    uint8_t shift;
    uint8_t address_len;
    uint16_t address_data=0,address_data_r=0;
    uint16_t index;

	GPIO_I2C_InitStruct=&GPIO_I2C_InitStructure;
	GPIO_I2C_InitStruct->I2C_SlaveAddress=slave;
    if (GPIO_I2C_CheckStructStatus(GPIO_I2C_InitStruct) == false)
    {
        APP_PRINT_INFO0("GPIO_I2C Check Struct Status error");
        return I2C_GPIO_INVALUE;
    }
    if (GPIO_I2C_InitStruct->busy_flag)

    {
        return I2C_GPIO_BUSY;
    }
    GPIO_I2C_InitStruct->busy_flag = true;
    if (GPIO_I2C_BUS_CHECK(GPIO_I2C_InitStruct))
    {
        GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
        return I2C_GPIO_BUSY;
    }

    
    if (GPIO_I2C_InitStruct->I2C_AddressMode)
    {
        address_data = (((GPIO_I2C_InitStruct->I2C_SlaveAddress >> 7) & 0xf6) | 0xf0) |
                       (GPIO_I2C_InitStruct->I2C_SlaveAddress << 8);
        address_data_r = (((GPIO_I2C_InitStruct->I2C_SlaveAddress >> 7) & 0xf6) | 0xf1) |
                       (GPIO_I2C_InitStruct->I2C_SlaveAddress << 8);        
    }
    else
    {
        address_data = (GPIO_I2C_InitStruct->I2C_SlaveAddress << 1) & 0xfe;
        address_data_r = address_data+1;//(GPIO_I2C_InitStruct->I2C_SlaveAddress << 1) | 0x0001;        
    }
	
	GPIO_I2C_start(GPIO_I2C_InitStruct);
    for (address_len = 0; address_len < (GPIO_I2C_InitStruct->I2C_AddressMode + 1); address_len++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((address_data >> address_len * 8) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            I2C_DELAY;


            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_ADDR_NOACK;
        }

    }
    for (index = 0; index < len; index++)
    {
        for (shift = 0; shift < 8; shift ++)
        {
#if SCL_HOLD
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
            while (timeout--)
            {
                if (GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitStruct))
                {
                    break;
                }
            }
            if (timeout == 0)
            {
                GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
                return I2C_GPIO_ERR_TIMEOUT;
            }
            GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
#endif
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((*(pBuf + index)) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            I2C_DELAY;
            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_TXDATA_NOACK;
        }
    }


    GPIO_I2C_restart(GPIO_I2C_InitStruct);
	
    for (address_len = 0; address_len < (GPIO_I2C_InitStruct->I2C_AddressMode + 1); address_len++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_OUT_SDA(GPIO_I2C_InitStruct);
            if (((address_data_r >> address_len * 8) >> (7 - shift)) & 0x01)
            {
                GPIO_I2C_SET_SDA(GPIO_I2C_InitStruct);
            }
            else
            {
                GPIO_I2C_RESET_SDA(GPIO_I2C_InitStruct);
            }
            I2C_DELAY;


            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
        }
        if (GPIO_I2C_wait_ack(GPIO_I2C_InitStruct) == 0)
        {
            GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
            return I2C_GPIO_ADDR_NOACK;
        }
    }

    for (index = 0; index < rlen; index++)
    {

        for (shift = 0; shift < 8; shift ++)
        {
#if SCL_HOLD
            uint16_t timeout = IIC_MAX_TIMEOUT_US;
            GPIO_I2C_free_SCL(GPIO_I2C_InitStruct);
            while (timeout--)
            {
                if (GPIO_I2C_SCL_HOLD_CHECK(GPIO_I2C_InitStruct))
                {
                    break;
                }
            }
            if (timeout == 0)
            {
                GPIO_I2C_BusClear(GPIO_I2C_InitStruct);
                return I2C_GPIO_ERR_TIMEOUT;
            }
            GPIO_I2C_OUT_SCL(GPIO_I2C_InitStruct);
#endif
            GPIO_I2C_RESET_SCL(GPIO_I2C_InitStruct);
            GPIO_I2C_free_SDA(GPIO_I2C_InitStruct);
            I2C_DELAY;
            GPIO_I2C_SET_SCL(GPIO_I2C_InitStruct);
            I2C_DELAY;
            if ((GPIO->DATAIN & GPIO_GetPin(GPIO_I2C_InitStruct->I2C_SDA_Pin)))
            {
                if(shift != 7)
                    *(prBuf + index) |= BIT(7 - shift);
                else
                    *(prBuf + index) |= 1;
            }
            else
            {
                if(shift != 7)
                    *(prBuf + index) &= ~BIT(7 - shift);
                else
                    *(prBuf + index) &= 0xfe;
            }
        }
        if (index == rlen - 1)
        {
            GPIO_I2C_send_nack(GPIO_I2C_InitStruct);
        }
        else
        {
            GPIO_I2C_send_ack(GPIO_I2C_InitStruct);
        }
    }


    GPIO_I2C_stop(GPIO_I2C_InitStruct);
    GPIO_I2C_InitStruct->busy_flag = false;
    return I2C_GPIO_Success;
}
									
//#define TEST_I2C_TIME
									
#ifdef TEST_I2C_TIME
#include "iqw_module_clock.h"
#endif // 
DATA_RAM_FUNCTION
GPIO_I2C_Status GPIO_TP_I2C_MasterWrite(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,uint16_t len)
{
	GPIO_I2C_Status state;
	
#ifdef TEST_I2C_TIME
		uint32_t startticks = iqw_module_rtc_get_ticks();
#endif 
	if( i2c_check_is_locked() )
    {
        return I2C_GPIO_BUSY; 
    }
	i2c_set_locked();
	state=GPIO_I2C_MasterWrite_int(GPIO_I2C_InitStruct, slave,pBuf,len);
	i2c_unset_locked();
#ifdef TEST_I2C_TIME
		uint32_t endticks = iqw_module_rtc_get_ticks();
		uint32_t diff = ((endticks - startticks) & 0xFFFFFF) * 1000 / 32768;
		LOG_INFO3("tp i2c write time = %d ms  slave=0x%x state=%d", diff ,slave,state);
#endif  
	if(I2C_GPIO_Success != state)
		LOG_INFO1("tp gpio i2c w err state=%d", state);
	return state;
}

GPIO_I2C_Status GPIO_TP_I2C_MasterWrite_no_p(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,uint16_t len)
{
	GPIO_I2C_Status state;
	
#ifdef TEST_I2C_TIME
		uint32_t startticks = iqw_module_rtc_get_ticks();
#endif 
	if( i2c_check_is_locked() )
    {
        return I2C_GPIO_BUSY; 
    }
	i2c_set_locked();
	state=GPIO_I2C_MasterWrite_int_no_p(GPIO_I2C_InitStruct, slave,pBuf,len);
	i2c_unset_locked();
#ifdef TEST_I2C_TIME
		uint32_t endticks = iqw_module_rtc_get_ticks();
		uint32_t diff = ((endticks - startticks) & 0xFFFFFF) * 1000 / 32768;
		LOG_INFO3("tp i2c write time = %d ms  slave=0x%x state=%d", diff ,slave,state);
#endif  
	if(I2C_GPIO_Success != state)
		LOG_INFO1("tp gpio i2c w no_p err state=%d", state);
	return state;
}
DATA_RAM_FUNCTION
GPIO_I2C_Status GPIO_TP_I2C_MasterRead(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,uint16_t len)
{
	GPIO_I2C_Status state;
#ifdef TEST_I2C_TIME
		uint32_t startticks = iqw_module_rtc_get_ticks();
#endif	
	if( i2c_check_is_locked() )
    {
        return I2C_GPIO_BUSY; 
    }
	i2c_set_locked();
	state=GPIO_I2C_MasterRead_int(GPIO_I2C_InitStruct, slave,pBuf,len);
	i2c_unset_locked();
#ifdef TEST_I2C_TIME
		uint32_t endticks = iqw_module_rtc_get_ticks();
		uint32_t diff = ((endticks - startticks) & 0xFFFFFF) * 1000 / 32768;
		LOG_INFO3("tp i2c read time = %d ms  slave=0x%x state=%d", diff ,slave,state);
#endif 	
	if(I2C_GPIO_Success != state)
		LOG_INFO1("tp gpio i2c r err state=%d", state);
	return state;
}

GPIO_I2C_Status GPIO_TP_I2C_MasterRead_no_p(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,uint16_t len)
{
	GPIO_I2C_Status state;
#ifdef TEST_I2C_TIME
		uint32_t startticks = iqw_module_rtc_get_ticks();
#endif	
	if( i2c_check_is_locked() )
    {
        return I2C_GPIO_BUSY; 
    }
	i2c_set_locked();
	state=GPIO_I2C_MasterRead_int_no_p(GPIO_I2C_InitStruct, slave,pBuf,len);
	i2c_unset_locked();
#ifdef TEST_I2C_TIME
		uint32_t endticks = iqw_module_rtc_get_ticks();
		uint32_t diff = ((endticks - startticks) & 0xFFFFFF) * 1000 / 32768;
		LOG_INFO3("tp i2c read time = %d ms  slave=0x%x state=%d", diff ,slave,state);
#endif 	
	if(I2C_GPIO_Success != state)
		LOG_INFO1("tp gpio i2c r no_p err state=%d", state);
	return state;
}

DATA_RAM_FUNCTION
GPIO_I2C_Status GPIO_TP_I2C_MasterRepeatRead(GPIO_I2C_InitTypeDef *GPIO_I2C_InitStruct, uint16_t slave,uint8_t *pBuf,uint16_t len,uint8_t *prBuf, uint16_t rlen)
{
	GPIO_I2C_Status state;
#ifdef TEST_I2C_TIME
		uint32_t startticks = iqw_module_rtc_get_ticks();
#endif	
	if( i2c_check_is_locked() )
    {
        return I2C_GPIO_BUSY; 
    }
	i2c_set_locked();
	state=GPIO_TP_I2C_MasterRepeatRead_int(GPIO_I2C_InitStruct, slave,pBuf,len,prBuf,rlen);
	i2c_unset_locked();
#ifdef TEST_I2C_TIME
		uint32_t endticks = iqw_module_rtc_get_ticks();
		uint32_t diff = ((endticks - startticks) & 0xFFFFFF) * 1000 / 32768;
		LOG_INFO3("i2c read time = %d ms  slave=0x%x state=%d", diff ,slave,state);
#endif 	
	if(I2C_GPIO_Success != state)
		LOG_INFO1("gpio tp i2c r repeat err state=%d", state);
	return state;
}
/******************* (C) COPYRIGHT 2015 Realtek Semiconductor Corporation *****END OF FILE****/

